#include "BasicInclude.h"
#include "DrawCube.h"

GLFWwindow * MainWindow;
int CurrentWidth;
int CurrentHeight;
const int WinWidth = 720;
const int WinHeight = 360;
const char * WinTitle = "MineCubeWorld 1.0 Beta";
const float sky_color_r = 0.0;
const float sky_color_g = 0.0;
const float sky_color_b = 1.0;
GLuint List_Cube;
float Player_x;
float Player_y;
float Player_z = 2;
float Lookupdown;
float Sceneroty;
float Visibility;
double mouse_x;
double mouse_y;
double lmouse_x;
double lmouse_y;
int xpos;
int ypos;
GLuint Texture[3];
char * MINECUBEWORLD_TEXTURE_BMP[3] = {
	".MineCubeWorld\\Texture\\dirt.bmp",
	".MineCubeWorld\\Texture\\grass_top.bmp",
	".MineCubeWorld\\Texture\\grass_side.bmp"
};

#ifdef _WIN32
const int sys_w = GetSystemMetrics(SM_CXSCREEN);
const int sys_h = GetSystemMetrics(SM_CYSCREEN);
#endif

void GetFPS() {
	static float FramesPerSecond = 0.0;
	static float LastTime = 0.0;
	float CurrentTime = GetTickCount() * 0.001;
	++FramesPerSecond;
	if (CurrentTime - LastTime > 1.0) {
		LastTime = CurrentTime;
		system("cls");
		printf_s("FPS:%d\n", int(FramesPerSecond));
		FramesPerSecond = 0;
	}
}

AUX_RGBImageRec * LoadBMP(char *Filename) {
	FILE * File = NULL;
	errno_t err;
	err = fopen_s(&File, Filename, "r");
	if (File) {
		fclose(File);
		return auxDIBImageLoad(Filename);
	}
	return NULL;
}

int loadtextures() {
	int Status = FALSE;
	AUX_RGBImageRec *TextureImage[3];
	memset(TextureImage, 0, sizeof(void *)*1);
	if (TextureImage[0] = LoadBMP(MINECUBEWORLD_TEXTURE_BMP[0])) {
		Status=TRUE;
		glGenTextures(1, &Texture[0]);
		glBindTexture(GL_TEXTURE_2D, Texture[0]);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MAG_FILTER,GL_NEAREST);
		glTexParameteri(GL_TEXTURE_2D,GL_TEXTURE_MIN_FILTER,GL_NEAREST);
		glTexImage2D(GL_TEXTURE_2D, 0, 3, TextureImage[0]->sizeX, TextureImage[0]->sizeY, 0, GL_RGB, GL_UNSIGNED_BYTE, TextureImage[0]->data);
	}
	if (TextureImage[0]) {
		if (TextureImage[0]->data) {
			free(TextureImage[0]->data);
		}
		free(TextureImage[0]);
	}
	return Status;
}

void Player_Mouse() {
	glfwGetCursorPos(MainWindow, &mouse_x, &mouse_y);
	Sceneroty -= (lmouse_x - mouse_x) / 10.0;
	Lookupdown -= (lmouse_y - mouse_y) / 10.0;
	glfwGetWindowPos(MainWindow, &xpos, &ypos);
	glfwSetCursorPos(MainWindow, CurrentWidth / 2, CurrentHeight / 2);
	glfwGetCursorPos(MainWindow, &mouse_x, &mouse_y);
	lmouse_x = mouse_x;
	lmouse_y = mouse_y;
}

void Player_Move() {
	if (glfwGetKey(MainWindow, GLFW_KEY_W)) { Player_x += 1; }
	else if (glfwGetKey(MainWindow, GLFW_KEY_S)) { Player_x -= 1; }
	else if (glfwGetKey(MainWindow, GLFW_KEY_A)) { Player_y += 1; }
	else if (glfwGetKey(MainWindow, GLFW_KEY_D)) { Player_y -= 1; }
	else if (glfwGetKey(MainWindow, GLFW_KEY_SPACE)) { Player_z += 1; }
	else if (glfwGetKey(MainWindow, GLFW_KEY_LEFT_SHIFT)) { Player_z -= 1; }
	else if (glfwGetKey(MainWindow, GLFW_KEY_RIGHT_SHIFT)) { Player_z -= 1; }

	if (Lookupdown > 89) Lookupdown = 89;
	if (Lookupdown < -89) Lookupdown = -89;
	if (Sceneroty > 360) Sceneroty -= 360;
	if (Sceneroty < 0) Sceneroty += 360;
}

void Draw_List_Cube(int Face) {
	if (Face > 6) { Face = 6; }
	if (Face < 1) { Face = 1; }
	if (Face == 1) { Cube_Face_1(); }
	else if (Face == 2) { Cube_Face_2(); }
	else if (Face == 3) { Cube_Face_3(); }
	else if (Face == 4) { Cube_Face_4(); }
	else if (Face == 5) { Cube_Face_5(); }
	else if (Face == 6) { Cube_Face_6(); }
}

GLuint Create_List() {
	GLuint Create_Cube_List;
	Create_Cube_List = glGenLists(1);
	glNewList(Create_Cube_List, GL_COMPILE);
	Draw_List_Cube(6);
	glEndList();
	return(Create_Cube_List);
}

void DrawMap() {
	glTranslatef(Player_y, -Player_z, Player_x);
	glRotatef(Lookupdown, 1, 0, 0);
	glRotatef(Sceneroty, 0, 1, 0);

	for (int i = -5; i < 5; i++) {
		for (int j = -5; j < 5; j++) {
			for (int x = -5; x < 5; x++) {
				glEnable(GL_TEXTURE_2D);
				glPushMatrix();
				glBindTexture(GL_TEXTURE_2D, Texture[0]);
				glTranslatef(i * 2, 0, j * 2);
				glCallList(List_Cube);
				glPopMatrix();
				glDisable(GL_TEXTURE_2D);
			}
			
		}
	}

	glLoadIdentity();
	glTranslatef(Player_y, -Player_z, Player_x);
	glfwSwapBuffers(MainWindow);
}

void UpdateWindow(int Width, int Height) {
	if (Height == 0) { Height = 1; }
	glViewport(0, 0, Width, Height);
	glMatrixMode(GL_PROJECTION);
	glLoadIdentity();
	gluPerspective(45.0f, (GLfloat)Width / (GLfloat)Height, 0.1, 1000);
	glMatrixMode(GL_MODELVIEW);
	glLoadIdentity();
}

void UpdateGame() {
	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
	glShadeModel(GL_SMOOTH);
	glClearColor(sky_color_r, sky_color_g, sky_color_b, 0);
	glClearDepth(1.0);
	glEnable(GL_DEPTH_TEST);
	glDepthFunc(GL_LEQUAL);
	glHint(GL_PERSPECTIVE_CORRECTION_HINT, GL_NICEST);
}

int main() {
	glfwInit();
	MainWindow = glfwCreateWindow(WinWidth, WinHeight, WinTitle, NULL, NULL);
	glfwSetWindowPos(MainWindow, sys_w / 2 - WinWidth / 2, sys_h / 2 - WinHeight / 2);
	glfwMakeContextCurrent(MainWindow);
	List_Cube = Create_List();
	ShowCursor(false);
	glfwGetCursorPos(MainWindow, &mouse_x, &mouse_y);
	lmouse_x = mouse_x;
	lmouse_y = mouse_y;
	glfwSetCursorPos(MainWindow, xpos + CurrentWidth / 2, ypos + CurrentHeight / 2);
	glfwSetCursorPos(MainWindow, CurrentWidth / 2, CurrentHeight / 2);
	loadtextures();
	do {
		glfwGetWindowSize(MainWindow, &CurrentWidth, &CurrentHeight);
		UpdateWindow(CurrentWidth, CurrentHeight);
		UpdateGame();
		Player_Mouse();
		Player_Move();
		DrawMap();
		GetFPS();
		if (glfwGetKey(MainWindow, GLFW_KEY_ESCAPE)) { exit(EXIT_SUCCESS); }
		glfwPollEvents();
	} while (!glfwWindowShouldClose(MainWindow));
	glfwTerminate();
	ShowCursor(true);
	return 0;
}
